#pragma warning(disable:4200)

#include "QCore.h"
#include "awtk.h"

//QDebug
QDebug::QDebug()
{

}

QDebug::~QDebug()
{
    printf("\n");
}

QDebug &QDebug::operator<<(int i)
{
    printf("%d ", i);
    return *this;
}

QDebug &QDebug::operator<<(double d)
{
    printf("%f ", d);
    return *this;
}

QDebug &QDebug::operator<<(const char *text)
{
    printf("%s ",text);
    return *this;
}

QDebug &QDebug::operator<<(void *ptr)
{
    printf("%p ", ptr);
    return *this;
}

//ObjectManager
ObjectManager g_objectManager;

void ObjectManager::connect(QObject *sender, int signal, QObject *recv, EventHandle handle,int outSignal)
{
    signalMap info;
    info.sender = sender;
    info.signal = signal;
    info.receiver = recv;
    info.handle = handle;
    info.outSignal = outSignal;
    m_signalMap.push_back(info);
}

void ObjectManager::emit(QObject *sender, int signal, void *args)
{
    for (size_t i = 0; i < m_signalMap.size(); i++)
    {
        signalMap &info = m_signalMap[i];
        if (info.sender == sender  && info.signal == signal)
        {
            m_sender = info.sender;
            if(info.handle)
                (info.receiver->*(info.handle))(args);
            if (info.outSignal)
                info.receiver->emit(info.outSignal, args);
            m_sender = NULL;
        }
    }
}

QObject *ObjectManager::sender()
{
    return m_sender;
}

//QMetaObject
QMetaObject::QMetaObject(const char *name, QMetaObject *super)
{
    m_name = name;
    m_super = super;
}

const QString &QMetaObject::className() const
{
    return m_name;
}

const QMetaObject *QMetaObject::superClass() const
{
    return m_super;
}

//QObject
QMetaObject QObject::ClassMeta("QObject",NULL);
QObject::QObject(QObject *parent)
{
    m_parent = parent;
    if(m_parent)
        m_parent->onChildAdd(this);
}

QObject::~QObject()
{
    for (int i = 0; i < m_childs.size(); i++)
        delete m_childs[i];
    if (m_parent)
        m_parent->onChildRemove(this);
}

void QObject::registEvent(EventHandle handle)
{

}

bool QObject::inherits(const QString &name) const
{
    const QMetaObject *info = meta();
    if (info)
    {
        if (info->className() == name)
            return true;

        info = info->superClass();
    }
    return false;
}

void QObject::connect(QObject *sender, int signal, QObject *recv, EventHandle handle)
{
    g_objectManager.connect(sender, signal, recv, handle,SIG_Invaild);
}

void QObject::connect(QObject *sender, int signal, QObject *recv, int trans_signal)
{
    g_objectManager.connect(sender, signal, recv, NULL, trans_signal);
}

void QObject::emit(int signal, void *args)
{
    g_objectManager.emit(this, signal, args);
}

QObject *QObject::sender()
{
    return g_objectManager.sender();
}

QObject *QObject::parent()
{
    return m_parent;
}

void QObject::setParent(QObject *object)
{
    Q_ASSERT(object != this);
    if (m_parent)
        m_parent->onChildRemove(this);

    m_parent = object;
    object->onChildAdd(this);
}

QString QObject::objectName() const
{
    return QString();
}

void QObject::setObjectName(const QString &name)
{

}

const QVariant &QObject::property(const char *name)
{
    return m_propMap[name];
}

void QObject::setProperty(const char *name, const QVariant &var)
{
    m_propMap.insert(name,var);
}

void QObject::deleteLater()
{

}

QString QObject::tr(const QString &str)
{
    return str;
}

void QObject::onChildAdd(QObject *object)
{
    m_childs.push_back(object);
}

void QObject::onChildRemove(QObject *object)
{
    m_childs.removeAll(object);
}

//QTimer
IMPLEMENT_META(QTimer,QObject)
static ret_t qtimer_on_timer(const timer_info_t* timer)
{
    return RET_OK;
}

QTimer::QTimer(QObject *object)
{
    m_interval = 0;
    m_single = false;
    m_timeId = 0;
}

void QTimer::start()
{
    start(m_interval);    
}

void QTimer::start(int ms)
{
    Q_ASSERT(m_timeId == 0);
    m_timeId = timer_add_with_type(qtimer_on_timer, this, m_interval, TIMER_INFO_NORMAL);
}

void QTimer::stop()
{
    Q_ASSERT(m_timeId != 0);
    timer_remove(m_timeId);
}

bool QTimer::isActive()
{
    return m_timeId != 0;
}

int QTimer::interval()
{
    return m_interval;
}

void QTimer::setInterval(int ms)
{
    m_interval = ms;
}

bool QTimer::isSingleShot()
{
    return m_single;
}

void QTimer::setSingleShot(bool flag)
{
    m_single = true;
}

//QSize
QSize::QSize(): wd(-1), ht(-1) {}

QSize::QSize(int w, int h): wd(w), ht(h) {}

bool QSize::isNull() const
{
    return wd == 0 && ht == 0;
}

bool QSize::isEmpty() const
{
    return wd<1 || ht<1;
}

bool QSize::isValid() const
{
    return wd >= 0 && ht >= 0;
}

int QSize::width() const
{
    return wd;
}

int QSize::height() const
{
    return ht;
}

void QSize::setWidth(int w)
{
    wd = w;
}

void QSize::setHeight(int h)
{
    ht = h;
}

QSize QSize::transposed() const
{
    return QSize(ht, wd);
}

void QSize::scale(int w, int h, Qt::AspectRatioMode mode)
{
    scale(QSize(w, h), mode);
}

void QSize::scale(const QSize &s, Qt::AspectRatioMode mode)
{
    *this = scaled(s, mode);
}

QSize QSize::scaled(int w, int h, Qt::AspectRatioMode mode) const
{
    return scaled(QSize(w, h), mode);
}

int &QSize::rwidth()
{
    return wd;
}

int &QSize::rheight()
{
    return ht;
}

QSize QSize::scaled(const QSize &s, Qt::AspectRatioMode mode) const
{
    if (mode == Qt::IgnoreAspectRatio || wd == 0 || ht == 0) {
        return s;
    }
    else {
        bool useHeight;
        qint64 rw = qint64(s.ht) * qint64(wd) / qint64(ht);

        if (mode == Qt::KeepAspectRatio) {
            useHeight = (rw <= s.wd);
        }
        else { // mode == Qt::KeepAspectRatioByExpanding
            useHeight = (rw >= s.wd);
        }

        if (useHeight) {
            return QSize((int)rw, s.ht);
        }
        else {
            return QSize(s.wd,
                qint32(qint64(s.wd) * qint64(ht) / qint64(wd)));
        }
    }
}

QSize &QSize::operator+=(const QSize &s)
{
    wd += s.wd; ht += s.ht; return *this;
}

QSize &QSize::operator-=(const QSize &s)
{
    wd -= s.wd; ht -= s.ht; return *this;
}

QSize &QSize::operator*=(qreal c)
{
    wd = qRound(wd*c); ht = qRound(ht*c); return *this;
}

bool operator==(const QSize &s1, const QSize &s2)
{
    return s1.wd == s2.wd && s1.ht == s2.ht;
}

bool operator!=(const QSize &s1, const QSize &s2)
{
    return s1.wd != s2.wd || s1.ht != s2.ht;
}

const QSize operator+(const QSize & s1, const QSize & s2)
{
    return QSize(s1.wd + s2.wd, s1.ht + s2.ht);
}

const QSize operator-(const QSize &s1, const QSize &s2)
{
    return QSize(s1.wd - s2.wd, s1.ht - s2.ht);
}

const QSize operator*(const QSize &s, qreal c)
{
    return QSize(qRound(s.wd*c), qRound(s.ht*c));
}

const QSize operator*(qreal c, const QSize &s)
{
    return QSize(qRound(s.wd*c), qRound(s.ht*c));
}

QSize &QSize::operator/=(qreal c)
{
    Q_ASSERT(!qFuzzyIsNull(c));
    wd = qRound(wd / c); ht = qRound(ht / c);
    return *this;
}

const QSize operator/(const QSize &s, qreal c)
{
    Q_ASSERT(!qFuzzyIsNull(c));
    return QSize(qRound(s.wd / c), qRound(s.ht / c));
}

QSize QSize::expandedTo(const QSize & otherSize) const
{
    return QSize(qMax(wd, otherSize.wd), qMax(ht, otherSize.ht));
}

QSize QSize::boundedTo(const QSize & otherSize) const
{
    return QSize(qMin(wd, otherSize.wd), qMin(ht, otherSize.ht));
}

//QColor
QColor::QColor()
{
    m_value.rgba = 0;
}

QColor::QColor(Qt::GlobalColor color)
{    
#define QRGB(r, g, b) \
    quint32(((0xffu << 24) | ((r & 0xff) << 16) | ((g & 0xff) << 8) | (b & 0xff)))
#define QRGBA(r, g, b, a) \
    quint32(((a & 0xff) << 24) | ((r & 0xff) << 16) | ((g & 0xff) << 8) | (b & 0xff))

    static const quint32 global_colors[] = {
        QRGB(255, 255, 255), // Qt::color0
        QRGB(0,   0,   0), // Qt::color1
        QRGB(0,   0,   0), // black
        QRGB(255, 255, 255), // white
                             /*
                             * From the "The Palette Manager: How and Why" by Ron Gery,
                             * March 23, 1992, archived on MSDN:
                             *
                             *     The Windows system palette is broken up into two
                             *     sections, one with fixed colors and one with colors
                             *     that can be changed by applications. The system palette
                             *     predefines 20 entries; these colors are known as the
                             *     static or reserved colors and consist of the 16 colors
                             *     found in the Windows version 3.0 VGA driver and 4
                             *     additional colors chosen for their visual appeal.  The
                             *     DEFAULT_PALETTE stock object is, as the name implies,
                             *     the default palette selected into a device context (DC)
                             *     and consists of these static colors. Applications can
                             *     set the remaining 236 colors using the Palette Manager.
                             *
                             * The 20 reserved entries have indices in [0,9] and
                             * [246,255]. We reuse 17 of them.
                             */
        QRGB(128, 128, 128), // index 248   medium gray
        QRGB(160, 160, 164), // index 247   light gray
        QRGB(192, 192, 192), // index 7     light gray
        QRGB(255,   0,   0), // index 249   red
        QRGB(0, 255,   0), // index 250   green
        QRGB(0,   0, 255), // index 252   blue
        QRGB(0, 255, 255), // index 254   cyan
        QRGB(255,   0, 255), // index 253   magenta
        QRGB(255, 255,   0), // index 251   yellow
        QRGB(128,   0,   0), // index 1     dark red
        QRGB(0, 128,   0), // index 2     dark green
        QRGB(0,   0, 128), // index 4     dark blue
        QRGB(0, 128, 128), // index 6     dark cyan
        QRGB(128,   0, 128), // index 5     dark magenta
        QRGB(128, 128,   0), // index 3     dark yellow
        QRGBA(0, 0, 0, 0)    //             transparent
    };
#undef QRGB
#undef QRGBA

    m_value.rgba = global_colors[color];
}

QColor::QColor(int r, int g, int b, int a)
{
    m_value.r = r;
    m_value.g = g;
    m_value.b = b;
    m_value.a = a;
}

int QColor::alpha() const
{
    return m_value.a;
}

void QColor::setAlpha(int alpha)
{
    m_value.a = alpha;
}

int QColor::red() const
{
    return m_value.r;
}

int QColor::green() const
{
    return m_value.g;
}

int QColor::blue() const
{
    return m_value.b;
}

void QColor::setRed(int red)
{
    m_value.r = red;
}

void QColor::setGreen(int green)
{
    m_value.g = green;
}

void QColor::setBlue(int blue)
{
    m_value.b = blue;
}

quint32 QColor::rgb() const
{
    return m_value.rgba;
}

quint32 QColor::rgba() const
{
    return m_value.rgba;
}

//QPoint
QPoint::QPoint() : xp(0), yp(0) {}

QPoint::QPoint(int xpos, int ypos) : xp(xpos), yp(ypos) {}

bool QPoint::isNull() const
{
    return xp == 0 && yp == 0;
}

int QPoint::x() const
{
    return xp;
}

int QPoint::y() const
{
    return yp;
}

void QPoint::setX(int xpos)
{
    xp = xpos;
}

void QPoint::setY(int ypos)
{
    yp = ypos;
}

int QPoint::manhattanLength() const
{
    return qAbs(x()) + qAbs(y());
}

int &QPoint::rx()
{
    return xp;
}

int &QPoint::ry()
{
    return yp;
}

QPoint &QPoint::operator+=(const QPoint &p)
{
    xp += p.xp; yp += p.yp; return *this;
}

QPoint &QPoint::operator-=(const QPoint &p)
{
    xp -= p.xp; yp -= p.yp; return *this;
}

QPoint &QPoint::operator*=(float factor)
{
    xp = qRound(xp*factor); yp = qRound(yp*factor); return *this;
}

QPoint &QPoint::operator*=(double factor)
{
    xp = qRound(xp*factor); yp = qRound(yp*factor); return *this;
}

QPoint &QPoint::operator*=(int factor)
{
    xp = xp*factor; yp = yp*factor; return *this;
}

bool operator==(const QPoint &p1, const QPoint &p2)
{
    return p1.xp == p2.xp && p1.yp == p2.yp;
}

bool operator!=(const QPoint &p1, const QPoint &p2)
{
    return p1.xp != p2.xp || p1.yp != p2.yp;
}

const QPoint operator+(const QPoint &p1, const QPoint &p2)
{
    return QPoint(p1.xp + p2.xp, p1.yp + p2.yp);
}

const QPoint operator-(const QPoint &p1, const QPoint &p2)
{
    return QPoint(p1.xp - p2.xp, p1.yp - p2.yp);
}

const QPoint operator*(const QPoint &p, float factor)
{
    return QPoint(qRound(p.xp*factor), qRound(p.yp*factor));
}

const QPoint operator*(const QPoint &p, double factor)
{
    return QPoint(qRound(p.xp*factor), qRound(p.yp*factor));
}

const QPoint operator*(const QPoint &p, int factor)
{
    return QPoint(p.xp*factor, p.yp*factor);
}

const QPoint operator*(float factor, const QPoint &p)
{
    return QPoint(qRound(p.xp*factor), qRound(p.yp*factor));
}

const QPoint operator*(double factor, const QPoint &p)
{
    return QPoint(qRound(p.xp*factor), qRound(p.yp*factor));
}

const QPoint operator*(int factor, const QPoint &p)
{
    return QPoint(p.xp*factor, p.yp*factor);
}

const QPoint operator+(const QPoint &p)
{
    return p;
}

const QPoint operator-(const QPoint &p)
{
    return QPoint(-p.xp, -p.yp);
}

QPoint &QPoint::operator/=(qreal c)
{
    xp = qRound(xp / c);
    yp = qRound(yp / c);
    return *this;
}

const QPoint operator/(const QPoint &p, qreal c)
{
    return QPoint(qRound(p.xp / c), qRound(p.yp / c));
}

//QPointF
QPointF::QPointF() : xp(0), yp(0) { }

QPointF::QPointF(qreal xpos, qreal ypos) : xp(xpos), yp(ypos) { }

QPointF::QPointF(const QPoint &p) : xp(p.x()), yp(p.y()) { }

qreal QPointF::manhattanLength() const
{
    return qAbs(x()) + qAbs(y());
}

bool QPointF::isNull() const
{
    return qIsNull(xp) && qIsNull(yp);
}

qreal QPointF::x() const
{
    return xp;
}

qreal QPointF::y() const
{
    return yp;
}

void QPointF::setX(qreal xpos)
{
    xp = xpos;
}

void QPointF::setY(qreal ypos)
{
    yp = ypos;
}

qreal &QPointF::rx()
{
    return xp;
}

qreal &QPointF::ry()
{
    return yp;
}

QPointF &QPointF::operator+=(const QPointF &p)
{
    xp += p.xp;
    yp += p.yp;
    return *this;
}

QPointF &QPointF::operator-=(const QPointF &p)
{
    xp -= p.xp; yp -= p.yp; return *this;
}

QPointF &QPointF::operator*=(qreal c)
{
    xp *= c; yp *= c; return *this;
}

bool operator==(const QPointF &p1, const QPointF &p2)
{
    return qFuzzyIsNull(p1.xp - p2.xp) && qFuzzyIsNull(p1.yp - p2.yp);
}

bool operator!=(const QPointF &p1, const QPointF &p2)
{
    return !qFuzzyIsNull(p1.xp - p2.xp) || !qFuzzyIsNull(p1.yp - p2.yp);
}

const QPointF operator+(const QPointF &p1, const QPointF &p2)
{
    return QPointF(p1.xp + p2.xp, p1.yp + p2.yp);
}

const QPointF operator-(const QPointF &p1, const QPointF &p2)
{
    return QPointF(p1.xp - p2.xp, p1.yp - p2.yp);
}

const QPointF operator*(const QPointF &p, qreal c)
{
    return QPointF(p.xp*c, p.yp*c);
}

const QPointF operator*(qreal c, const QPointF &p)
{
    return QPointF(p.xp*c, p.yp*c);
}

const QPointF operator+(const QPointF &p)
{
    return p;
}

const QPointF operator-(const QPointF &p)
{
    return QPointF(-p.xp, -p.yp);
}

QPointF &QPointF::operator/=(qreal divisor)
{
    xp /= divisor;
    yp /= divisor;
    return *this;
}

const QPointF operator/(const QPointF &p, qreal divisor)
{
    return QPointF(p.xp / divisor, p.yp / divisor);
}

QPoint QPointF::toPoint() const
{
    return QPoint(qRound(xp), qRound(yp));
}

//QRect
QRect::QRect(int aleft, int atop, int awidth, int aheight)
    : x1(aleft), y1(atop), x2(aleft + awidth - 1), y2(atop + aheight - 1) {}

QRect::QRect(const QPoint &atopLeft, const QPoint &abottomRight)
    : x1(atopLeft.x()), y1(atopLeft.y()), x2(abottomRight.x()), y2(abottomRight.y()) {}

QRect::QRect(const QPoint &atopLeft, const QSize &asize)
    : x1(atopLeft.x()), y1(atopLeft.y()), x2(atopLeft.x() + asize.width() - 1), y2(atopLeft.y() + asize.height() - 1) {}

bool QRect::isNull() const
{
    return x2 == x1 - 1 && y2 == y1 - 1;
}

bool QRect::isEmpty() const
{
    return x1 > x2 || y1 > y2;
}

bool QRect::isValid() const
{
    return x1 <= x2 && y1 <= y2;
}

int QRect::left() const
{
    return x1;
}

int QRect::top() const
{
    return y1;
}

int QRect::right() const
{
    return x2;
}

int QRect::bottom() const
{
    return y2;
}

int QRect::x() const
{
    return x1;
}

int QRect::y() const
{
    return y1;
}

void QRect::setLeft(int pos)
{
    x1 = pos;
}

void QRect::setTop(int pos)
{
    y1 = pos;
}

void QRect::setRight(int pos)
{
    x2 = pos;
}

void QRect::setBottom(int pos)
{
    y2 = pos;
}

void QRect::setTopLeft(const QPoint &p)
{
    x1 = p.x(); y1 = p.y();
}

void QRect::setBottomRight(const QPoint &p)
{
    x2 = p.x(); y2 = p.y();
}

void QRect::setTopRight(const QPoint &p)
{
    x2 = p.x(); y1 = p.y();
}

void QRect::setBottomLeft(const QPoint &p)
{
    x1 = p.x(); y2 = p.y();
}

void QRect::setX(int ax)
{
    x1 = ax;
}

void QRect::setY(int ay)
{
    y1 = ay;
}

QPoint QRect::topLeft() const
{
    return QPoint(x1, y1);
}

QPoint QRect::bottomRight() const
{
    return QPoint(x2, y2);
}

QPoint QRect::topRight() const
{
    return QPoint(x2, y1);
}

QPoint QRect::bottomLeft() const
{
    return QPoint(x1, y2);
}

QPoint QRect::center() const
{
    return QPoint(int((qint64(x1) + x2) / 2), int((qint64(y1) + y2) / 2));
} // cast avoids overflow on addition

QRect QRect::normalized() const
{
    QRect r;
    if (x2 < x1 - 1) {                                // swap bad x values
        r.x1 = x2;
        r.x2 = x1;
    }
    else {
        r.x1 = x1;
        r.x2 = x2;
    }
    if (y2 < y1 - 1) {                                // swap bad y values
        r.y1 = y2;
        r.y2 = y1;
    }
    else {
        r.y1 = y1;
        r.y2 = y2;
    }
    return r;
}

bool QRect::contains(const QPoint &p, bool proper) const
{
    int l, r;
    if (x2 < x1 - 1) {
        l = x2;
        r = x1;
    }
    else {
        l = x1;
        r = x2;
    }
    if (proper) {
        if (p.x() <= l || p.x() >= r)
            return false;
    }
    else {
        if (p.x() < l || p.x() > r)
            return false;
    }
    int t, b;
    if (y2 < y1 - 1) {
        t = y2;
        b = y1;
    }
    else {
        t = y1;
        b = y2;
    }
    if (proper) {
        if (p.y() <= t || p.y() >= b)
            return false;
    }
    else {
        if (p.y() < t || p.y() > b)
            return false;
    }
    return true;
}

bool QRect::contains(const QRect &r, bool proper) const
{
    if (isNull() || r.isNull())
        return false;

    int l1 = x1;
    int r1 = x1;
    if (x2 - x1 + 1 < 0)
        l1 = x2;
    else
        r1 = x2;

    int l2 = r.x1;
    int r2 = r.x1;
    if (r.x2 - r.x1 + 1 < 0)
        l2 = r.x2;
    else
        r2 = r.x2;

    if (proper) {
        if (l2 <= l1 || r2 >= r1)
            return false;
    }
    else {
        if (l2 < l1 || r2 > r1)
            return false;
    }

    int t1 = y1;
    int b1 = y1;
    if (y2 - y1 + 1 < 0)
        t1 = y2;
    else
        b1 = y2;

    int t2 = r.y1;
    int b2 = r.y1;
    if (r.y2 - r.y1 + 1 < 0)
        t2 = r.y2;
    else
        b2 = r.y2;

    if (proper) {
        if (t2 <= t1 || b2 >= b1)
            return false;
    }
    else {
        if (t2 < t1 || b2 > b1)
            return false;
    }

    return true;
}

int QRect::width() const
{
    return  x2 - x1 + 1;
}

int QRect::height() const
{
    return  y2 - y1 + 1;
}

QSize QRect::size() const
{
    return QSize(width(), height());
}

void QRect::translate(int dx, int dy)
{
    x1 += dx;
    y1 += dy;
    x2 += dx;
    y2 += dy;
}

void QRect::translate(const QPoint &p)
{
    x1 += p.x();
    y1 += p.y();
    x2 += p.x();
    y2 += p.y();
}

QRect QRect::translated(int dx, int dy) const
{
    return QRect(QPoint(x1 + dx, y1 + dy), QPoint(x2 + dx, y2 + dy));
}

QRect QRect::translated(const QPoint &p) const
{
    return QRect(QPoint(x1 + p.x(), y1 + p.y()), QPoint(x2 + p.x(), y2 + p.y()));
}

void QRect::moveTo(int ax, int ay)
{
    x2 += ax - x1;
    y2 += ay - y1;
    x1 = ax;
    y1 = ay;
}

void QRect::moveTo(const QPoint &p)
{
    x2 += p.x() - x1;
    y2 += p.y() - y1;
    x1 = p.x();
    y1 = p.y();
}

void QRect::moveLeft(int pos)
{
    x2 += (pos - x1); x1 = pos;
}

void QRect::moveTop(int pos)
{
    y2 += (pos - y1); y1 = pos;
}

void QRect::moveRight(int pos)
{
    x1 += (pos - x2);
    x2 = pos;
}

void QRect::moveBottom(int pos)
{
    y1 += (pos - y2);
    y2 = pos;
}

void QRect::moveTopLeft(const QPoint &p)
{
    moveLeft(p.x());
    moveTop(p.y());
}

void QRect::moveBottomRight(const QPoint &p)
{
    moveRight(p.x());
    moveBottom(p.y());
}

void QRect::moveTopRight(const QPoint &p)
{
    moveRight(p.x());
    moveTop(p.y());
}

void QRect::moveBottomLeft(const QPoint &p)
{
    moveLeft(p.x());
    moveBottom(p.y());
}

void QRect::moveCenter(const QPoint &p)
{
    int w = x2 - x1;
    int h = y2 - y1;
    x1 = p.x() - w / 2;
    y1 = p.y() - h / 2;
    x2 = x1 + w;
    y2 = y1 + h;
}

void QRect::getRect(int *ax, int *ay, int *aw, int *ah) const
{
    *ax = x1;
    *ay = y1;
    *aw = x2 - x1 + 1;
    *ah = y2 - y1 + 1;
}

void QRect::setRect(int ax, int ay, int aw, int ah)
{
    x1 = ax;
    y1 = ay;
    x2 = (ax + aw - 1);
    y2 = (ay + ah - 1);
}

void QRect::getCoords(int *xp1, int *yp1, int *xp2, int *yp2) const
{
    *xp1 = x1;
    *yp1 = y1;
    *xp2 = x2;
    *yp2 = y2;
}

void QRect::setCoords(int xp1, int yp1, int xp2, int yp2)
{
    x1 = xp1;
    y1 = yp1;
    x2 = xp2;
    y2 = yp2;
}

QRect QRect::adjusted(int xp1, int yp1, int xp2, int yp2) const
{
    return QRect(QPoint(x1 + xp1, y1 + yp1), QPoint(x2 + xp2, y2 + yp2));
}

void QRect::adjust(int dx1, int dy1, int dx2, int dy2)
{
    x1 += dx1;
    y1 += dy1;
    x2 += dx2;
    y2 += dy2;
}

void QRect::setWidth(int w)
{
    x2 = (x1 + w - 1);
}

void QRect::setHeight(int h)
{
    y2 = (y1 + h - 1);
}

void QRect::setSize(const QSize &s)
{
    x2 = (s.width() + x1 - 1);
    y2 = (s.height() + y1 - 1);
}

bool QRect::contains(int ax, int ay, bool aproper) const
{
    return contains(QPoint(ax, ay), aproper);
}

bool QRect::contains(int ax, int ay) const
{
    return contains(QPoint(ax, ay), false);
}

QRect& QRect::operator|=(const QRect &r)
{
    *this = *this | r;
    return *this;
}

QRect& QRect::operator&=(const QRect &r)
{
    *this = *this & r;
    return *this;
}

QRect QRect::intersected(const QRect &other) const
{
    return *this & other;
}

QRect QRect::united(const QRect &r) const
{
    return *this | r;
}

QRect QRect::operator|(const QRect &r) const
{
    if (isNull())
        return r;
    if (r.isNull())
        return *this;

    int l1 = x1;
    int r1 = x1;
    if (x2 - x1 + 1 < 0)
        l1 = x2;
    else
        r1 = x2;

    int l2 = r.x1;
    int r2 = r.x1;
    if (r.x2 - r.x1 + 1 < 0)
        l2 = r.x2;
    else
        r2 = r.x2;

    int t1 = y1;
    int b1 = y1;
    if (y2 - y1 + 1 < 0)
        t1 = y2;
    else
        b1 = y2;

    int t2 = r.y1;
    int b2 = r.y1;
    if (r.y2 - r.y1 + 1 < 0)
        t2 = r.y2;
    else
        b2 = r.y2;

    QRect tmp;
    tmp.x1 = qMin(l1, l2);
    tmp.x2 = qMax(r1, r2);
    tmp.y1 = qMin(t1, t2);
    tmp.y2 = qMax(b1, b2);
    return tmp;
}


QRect QRect::operator&(const QRect &r) const
{
    if (isNull() || r.isNull())
        return QRect();

    int l1 = x1;
    int r1 = x1;
    if (x2 - x1 + 1 < 0)
        l1 = x2;
    else
        r1 = x2;

    int l2 = r.x1;
    int r2 = r.x1;
    if (r.x2 - r.x1 + 1 < 0)
        l2 = r.x2;
    else
        r2 = r.x2;

    if (l1 > r2 || l2 > r1)
        return QRect();

    int t1 = y1;
    int b1 = y1;
    if (y2 - y1 + 1 < 0)
        t1 = y2;
    else
        b1 = y2;

    int t2 = r.y1;
    int b2 = r.y1;
    if (r.y2 - r.y1 + 1 < 0)
        t2 = r.y2;
    else
        b2 = r.y2;

    if (t1 > b2 || t2 > b1)
        return QRect();

    QRect tmp;
    tmp.x1 = qMax(l1, l2);
    tmp.x2 = qMin(r1, r2);
    tmp.y1 = qMax(t1, t2);
    tmp.y2 = qMin(b1, b2);
    return tmp;
}

bool operator==(const QRect &r1, const QRect &r2)
{
    return r1.x1 == r2.x1 && r1.x2 == r2.x2 && r1.y1 == r2.y1 && r1.y2 == r2.y2;
}

bool operator!=(const QRect &r1, const QRect &r2)
{
    return r1.x1 != r2.x1 || r1.x2 != r2.x2 || r1.y1 != r2.y1 || r1.y2 != r2.y2;
}

QDebug &operator<<(QDebug &dbg, const QRect &rc)
{
    return dbg << "{" << rc.x() << "," << rc.y() << "," << rc.width() <<  "," << rc.height() << "}";
}

//QLine
QLine::QLine() { }

QLine::QLine(const QPoint &pt1_, const QPoint &pt2_) : pt1(pt1_), pt2(pt2_) { }

QLine::QLine(int x1pos, int y1pos, int x2pos, int y2pos) : pt1(QPoint(x1pos, y1pos)), pt2(QPoint(x2pos, y2pos)) { }

bool QLine::isNull() const
{
    return pt1 == pt2;
}

int QLine::x1() const
{
    return pt1.x();
}

int QLine::y1() const
{
    return pt1.y();
}

int QLine::x2() const
{
    return pt2.x();
}

int QLine::y2() const
{
    return pt2.y();
}

QPoint QLine::p1() const
{
    return pt1;
}

QPoint QLine::p2() const
{
    return pt2;
}

int QLine::dx() const
{
    return pt2.x() - pt1.x();
}

int QLine::dy() const
{
    return pt2.y() - pt1.y();
}

void QLine::translate(const QPoint &point)
{
    pt1 += point;
    pt2 += point;
}

void QLine::translate(int adx, int ady)
{
    this->translate(QPoint(adx, ady));
}

QLine QLine::translated(const QPoint &p) const
{
    return QLine(pt1 + p, pt2 + p);
}

QLine QLine::translated(int adx, int ady) const
{
    return translated(QPoint(adx, ady));
}

void QLine::setP1(const QPoint &aP1)
{
    pt1 = aP1;
}

void QLine::setP2(const QPoint &aP2)
{
    pt2 = aP2;
}

void QLine::setPoints(const QPoint &aP1, const QPoint &aP2)
{
    pt1 = aP1;
    pt2 = aP2;
}

void QLine::setLine(int aX1, int aY1, int aX2, int aY2)
{
    pt1 = QPoint(aX1, aY1);
    pt2 = QPoint(aX2, aY2);
}

bool QLine::operator==(const QLine &d) const
{
    return pt1 == d.pt1 && pt2 == d.pt2;
}

//QLineF

QLineF::QLineF()
{
}

QLineF::QLineF(const QPointF &apt1, const QPointF &apt2)
    : pt1(apt1), pt2(apt2)
{
}

QLineF::QLineF(qreal x1pos, qreal y1pos, qreal x2pos, qreal y2pos)
    : pt1(x1pos, y1pos), pt2(x2pos, y2pos)
{
}

qreal QLineF::x1() const
{
    return pt1.x();
}

qreal QLineF::y1() const
{
    return pt1.y();
}

qreal QLineF::x2() const
{
    return pt2.x();
}

qreal QLineF::y2() const
{
    return pt2.y();
}

bool QLineF::isNull() const
{
    return qFuzzyCompare(pt1.x(), pt2.x()) && qFuzzyCompare(pt1.y(), pt2.y());
}

QPointF QLineF::p1() const
{
    return pt1;
}

QPointF QLineF::p2() const
{
    return pt2;
}

qreal QLineF::dx() const
{
    return pt2.x() - pt1.x();
}

qreal QLineF::dy() const
{
    return pt2.y() - pt1.y();
}

QLineF QLineF::normalVector() const
{
    return QLineF(p1(), p1() + QPointF(dy(), -dx()));
}

void QLineF::translate(const QPointF &point)
{
    pt1 += point;
    pt2 += point;
}

void QLineF::translate(qreal adx, qreal ady)
{
    this->translate(QPointF(adx, ady));
}

QLineF QLineF::translated(const QPointF &p) const
{
    return QLineF(pt1 + p, pt2 + p);
}

QLineF QLineF::translated(qreal adx, qreal ady) const
{
    return translated(QPointF(adx, ady));
}

void QLineF::setLength(qreal len)
{
    if (isNull())
        return;
    QLineF v = unitVector();
    pt2 = QPointF(pt1.x() + v.dx() * len, pt1.y() + v.dy() * len);
}

QPointF QLineF::pointAt(qreal t) const
{
    return QPointF(pt1.x() + (pt2.x() - pt1.x()) * t, pt1.y() + (pt2.y() - pt1.y()) * t);
}

QLine QLineF::toLine() const
{
    return QLine(pt1.toPoint(), pt2.toPoint());
}


void QLineF::setP1(const QPointF &aP1)
{
    pt1 = aP1;
}

void QLineF::setP2(const QPointF &aP2)
{
    pt2 = aP2;
}

void QLineF::setPoints(const QPointF &aP1, const QPointF &aP2)
{
    pt1 = aP1;
    pt2 = aP2;
}

void QLineF::setLine(qreal aX1, qreal aY1, qreal aX2, qreal aY2)
{
    pt1 = QPointF(aX1, aY1);
    pt2 = QPointF(aX2, aY2);
}


bool QLineF::operator==(const QLineF &d) const
{
    return pt1 == d.pt1 && pt2 == d.pt2;
}

qreal QLineF::length() const
{
    qreal x = pt2.x() - pt1.x();
    qreal y = pt2.y() - pt1.y();
    return qSqrt(x*x + y*y);
}

qreal QLineF::angle() const
{
    const qreal dx = pt2.x() - pt1.x();
    const qreal dy = pt2.y() - pt1.y();

    const qreal theta = qAtan2(-dy, dx) * 360.0 / M_2PI;

    const qreal theta_normalized = theta < 0 ? theta + 360 : theta;

    if (qFuzzyCompare(theta_normalized, qreal(360)))
        return qreal(0);
    else
        return theta_normalized;
}

void QLineF::setAngle(qreal angle)
{
    const qreal angleR = angle * M_2PI / 360.0;
    const qreal l = length();

    const qreal dx = qCos(angleR) * l;
    const qreal dy = -qSin(angleR) * l;

    pt2.rx() = pt1.x() + dx;
    pt2.ry() = pt1.y() + dy;
}

QLineF QLineF::fromPolar(qreal length, qreal angle)
{
    const qreal angleR = angle * M_2PI / 360.0;
    return QLineF(0, 0, qCos(angleR) * length, -qSin(angleR) * length);
}

QLineF QLineF::unitVector() const
{
    qreal x = pt2.x() - pt1.x();
    qreal y = pt2.y() - pt1.y();

    qreal len = qSqrt(x*x + y*y);
    QLineF f(p1(), QPointF(pt1.x() + x / len, pt1.y() + y / len));

#ifndef QT_NO_DEBUG
    if (qAbs(f.length() - 1) >= 0.001)
        qWarning("QLine::unitVector: New line does not have unit length");
#endif

    return f;
}

QLineF::IntersectType QLineF::intersect(const QLineF &l, QPointF *intersectionPoint) const
{
    // ipmlementation is based on Graphics Gems III's "Faster Line Segment Intersection"
    const QPointF a = pt2 - pt1;
    const QPointF b = l.pt1 - l.pt2;
    const QPointF c = pt1 - l.pt1;

    const qreal denominator = a.y() * b.x() - a.x() * b.y();
    if (denominator == 0)
        return NoIntersection;

    const qreal reciprocal = 1 / denominator;
    const qreal na = (b.y() * c.x() - b.x() * c.y()) * reciprocal;
    if (intersectionPoint)
        *intersectionPoint = pt1 + a * na;

    if (na < 0 || na > 1)
        return UnboundedIntersection;

    const qreal nb = (a.x() * c.y() - a.y() * c.x()) * reciprocal;
    if (nb < 0 || nb > 1)
        return UnboundedIntersection;

    return BoundedIntersection;
}


//QLineF
qreal QLineF::angleTo(const QLineF &l) const
{
    if (isNull() || l.isNull())
        return 0;

    const qreal a1 = angle();
    const qreal a2 = l.angle();

    const qreal delta = a2 - a1;
    const qreal delta_normalized = delta < 0 ? delta + 360 : delta;

    if (qFuzzyCompare(delta, qreal(360)))
        return 0;
    else
        return delta_normalized;
}

qreal QLineF::angle(const QLineF &l) const
{
    if (isNull() || l.isNull())
        return 0;
    qreal cos_line = (dx()*l.dx() + dy()*l.dy()) / (length()*l.length());
    qreal rad = 0;
    // only accept cos_line in the range [-1,1], if it is outside, use 0 (we return 0 rather than PI for those cases)
    if (cos_line >= -1.0 && cos_line <= 1.0) rad = qAcos(cos_line);
    return rad * 360 / M_2PI;
}

//QString
QString QString::number(int value)
{
    char buffer[32];
    ::sprintf(buffer, "%d", value);
    return buffer;
}

QString QString::number(double value)
{
    char buffer[32];
    ::sprintf(buffer, "%f", value);
    return buffer;
}

QString::QString()
{

}

QString::QString(const char *str)
{
    m_str = str;
}

bool QString::isEmpty() const
{
    return m_str.size() == 0;
}

int QString::size() const
{
    return m_str.size();
}

QString QString::mid(int start, int len) const
{
    QString ret;
    ret.m_str = this->m_str.substr(start, len);
    return ret;
}

QString QString::toLower() const
{
    QString other = *this;
    for (size_t i = 0; i < other.m_str.size(); i++)
    {
        if (isupper(other.m_str[i]))
            other.m_str[i] = tolower(other.m_str[i]);
    }
    return other;
}

QString QString::toUpper() const
{
    QString other = *this;
    for (size_t i = 0; i < other.m_str.size(); i++)
    {
        if (islower(other.m_str[i]))
            other.m_str[i] = toupper(other.m_str[i]);
    }
    return other;
}

int QString::toInt(bool *ok)
{
    return 3;
}

double QString::toDouble(bool *ok)
{
    return 0;
}

QString &QString::append(const QString &str)
{
    m_str += str.m_str;
    return *this;
}

QString &QString::append(const char *str)
{
    m_str += str;
    return *this;
}

int QString::compare(const QString &other, Qt::CaseSensitivity cs) const
{
    Q_ASSERT(0);
    return true;
}

bool QString::startsWith(const QString &s, Qt::CaseSensitivity cs) const
{
    Q_ASSERT(0);
    return true;
}

bool QString::endsWith(const QString &s, Qt::CaseSensitivity cs) const
{
    Q_ASSERT(0);
    return true;
}

QStringList QString::split(const QString &sep, QString::SplitBehavior behavior, Qt::CaseSensitivity cs) const
{
    QStringList ret;
    const QString *src = this;
    const QString *find = &sep;
    QString tmp1, tmp2;
    if (cs == Qt::CaseInsensitive)
    {
        tmp1 = this->toLower();
        tmp2 = sep.toLower();
        src = &tmp1;
        find = &tmp2;
    }

    int start = -1;
    do
    {
        int end = src->indexOf(*find, start + 1);
        int next = end;
        if (end == -1)
            end = size();
        if (end - start >= 2)
            ret.push_back(this->mid(start + 1, end - (start + 1)));
        else if (behavior == QString::KeepEmptyParts)
            ret.push_back(QString());
        
        start = next;
    } while (start >= 0);

    return ret;
}

int QString::indexOf(const QString &str, int from, Qt::CaseSensitivity cs) const
{
    size_t pos;
    if(cs = Qt::CaseSensitive)
        pos = m_str.find(str.m_str, from);
    else
    {
        QString tmp1 = this->toLower();
        QString tmp2 = str.toLower();
        pos = tmp1.m_str.find(tmp2.m_str, from);
    }

    if (pos != string::npos)
        return (int)pos;
    else
        return -1;
}

int QString::lastIndexOf(const QString &str, int from, Qt::CaseSensitivity cs) const
{
    if (from == -1)
        from = size() - 1;

    size_t pos;    
    if (cs = Qt::CaseSensitive)
        pos = m_str.rfind(str.m_str, from);
    else
    {
        QString tmp1 = this->toLower();
        QString tmp2 = str.toLower();
        pos = tmp1.m_str.rfind(tmp2.m_str, from);
    }

    if (pos != string::npos)
        return (int)pos;
    else
        return -1;
}

QString &QString::insert(int position, const QString &str)
{
    Q_ASSERT(0);
    return *this;
}

void QString::replace(const QString &before, QString after, Qt::CaseSensitivity cs)
{
    Q_ASSERT(0);
}

QString &QString::sprintf(const char *cformat, ...)
{
    va_list ap;
    va_start(ap, cformat);

    char buffer[128];
    vsnprintf(buffer, 128, cformat,ap);
    va_end(ap);

    m_str = buffer;
    return *this;
}

const char *QString::c_str() const
{
    return m_str.c_str();
}

bool QString::operator==(const QString &other) const
{
    return this->m_str == other.m_str;
}

bool QString::operator!=(const QString &other) const
{
    return this->m_str != other.m_str;
}

bool QString::operator<(const QString &other) const
{
    return this->m_str < other.m_str;
}

bool QString::operator>(const QString &other) const
{
    return this->m_str > other.m_str;
}

QString &QString::operator+=(const QString &other)
{
    this->m_str += other.m_str;
    return *this;
}

QString operator+(const QString &s1, const QString &s2)
{
    return QString((s1.m_str + s2.m_str).c_str());
}

QDebug &operator<<(QDebug &dbg, const QString &str)
{
    return dbg << str.c_str();
}

//QStringList
QString QStringList::join(const QString &sep)
{
    QString ret;
    for (size_t i = 0; i < m_vector.size(); i++)
    {
        ret += m_vector[i];
        if (i != m_vector.size() - 1)
            ret += sep;
    }
    return ret;
}

//QVariant
QVariant::QVariant()
{

}

QVariant::QVariant(int i)
{

}

QVariant::QVariant(double d)
{

}

QVariant::QVariant(const QString &str)
{

}

QVariant::~QVariant()
{

}

int QVariant::toInt() const
{
    return 0;
}

double QVariant::toDouble() const
{
    return 0;
}

QString QVariant::toString() const
{
    return QString();
}